home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Viewer How-To CD / Microsoft Multimedia Viewer How-To CD.iso / mvsample / progsamp / katasrch / results.c < prev    next >
C/C++ Source or Header  |  1993-03-21  |  18KB  |  614 lines

  1. #include <windows.h>
  2. #include <viewer.h>
  3. #include <stdlib.h>
  4.  
  5. #include "katasrch.h"
  6. #include "results.h"
  7. #include "mvbtask.h"
  8.  
  9. /***********************************************************************
  10.  * SubmitJumpAddr
  11.  *
  12.  * Sends a JumpAddr command to the specified Viewer instance.
  13.  ***********************************************************************/
  14.  
  15. int SubmitJumpAddr(
  16.     VWR  vwr,           // Handle to a Viewer instance
  17.     LONG lAddr)         // Topic address to jump to
  18. {
  19.     char   szCommand[64];   // Command to submit
  20.  
  21.     // Build the JumpAddr command and submit it to Viewer
  22.  
  23.     wsprintf(szCommand,"JumpAddr(%ld)", lAddr);
  24.  
  25.     if(VwrCommand(vwr, NULL, szCommand, FALSE) != vwr)
  26.         return KSERR_NOVWR;
  27.     else
  28.         return 0;
  29. }
  30.  
  31.  
  32.  
  33. /************************************************************************
  34.  * DisplayTopic
  35.  *
  36.  * Displays a topic that was double-clicked in a list box
  37.  ************************************************************************/
  38.  
  39. int DisplayTopic(
  40.     HTITLE htitle,      // Handle to title (from TitleOpen)
  41.     VWR    vwr,         // Viewer identifer (from VwrFromMVB)
  42.     LONG   lTopicNo)    // Topic number
  43. {
  44.     LONG   lTopicAddr;  // Topic address of selection
  45.  
  46.     // Get topic address from title
  47.  
  48.     lTopicAddr = TitleGetInfo(htitle, TTLINF_TOPICADDR, lTopicNo, 0L);
  49.     if(lTopicAddr == -1)
  50.         return KSERR_DISPLAYGETINFO;
  51.  
  52.     return SubmitJumpAddr(vwr, lTopicAddr);
  53. }
  54.  
  55.  
  56.  
  57. /**********************************************************************
  58.  * SetHighlight
  59.  *
  60.  * Issues a Highlight command for the specified hHighlight and title.
  61.  *
  62.  **********************************************************************/
  63.  
  64. void SetHighlight(
  65.     VWR    vwr,         // Handle to Viewer (from VwrFromMVB)
  66.     HANDLE hHighlight)  // Highlight info (from TopicListFromQuery)
  67. {
  68.     char szCmd[24];
  69.  
  70.     wsprintf(szCmd,"Highlight(%u)", hHighlight);
  71.  
  72.     VwrCommand(vwr, NULL, szCmd, FALSE);
  73. }
  74.  
  75.  
  76. /**********************************************************************
  77.  * AddTopicTitle
  78.  *
  79.  * Adds a topic title to the Results list box.
  80.  *
  81.  **********************************************************************/
  82.  
  83. int AddTopicTitle(
  84.     HWND   hwndLB,      // Results list box handle
  85.     HTITLE htitle,      // Handle to title
  86.     HTLIST htl,         // Handle to topic list
  87.     LONG   lTopic)      // Index of topic-list entry to add
  88. {
  89.     LONG lRet, lTopicNum;
  90.     char szTitle[128];
  91.  
  92.     // Get the topic number
  93.  
  94.     lTopicNum = TopicListLookup(htl, lTopic);
  95.  
  96.     if(lTopicNum == -1)
  97.     {
  98.         return KSERR_TOPICLOOKUP;
  99.     }
  100.  
  101.     // Get the topic title
  102.  
  103.     lRet = TitleGetInfo(htitle, TTLINF_TOPICTITLE, lTopicNum, 
  104.                          (LONG)(LPSTR)szTitle);
  105.     if(lRet == -1)
  106.     {
  107.         // Report error
  108.  
  109.         return KSERR_TOPICGETINFO;
  110.     }
  111.  
  112.     SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szTitle);
  113.  
  114.     return 0;                              // Indicate more topics
  115. }
  116.  
  117.  
  118. /**************************************************************************
  119.  * InitResultsControls
  120.  *
  121.  * Creates the controls used in the results windows and sets their fonts.
  122.  **************************************************************************/
  123.  
  124. void InitResultsControls(
  125.     HWND  hwnd,             // Handle of results window
  126.     HFONT hfont)            // Font to use
  127. {
  128.     if(hfont)
  129.     {
  130.         SendDlgItemMessage(hwnd, ID_RESULTS_LIST, WM_SETFONT, 
  131.                             (WPARAM)hfont, TRUE);
  132.         SendDlgItemMessage(hwnd, ID_RESULTS_PREVIOUS, WM_SETFONT, 
  133.                             (WPARAM)hfont, TRUE);
  134.         SendDlgItemMessage(hwnd, ID_RESULTS_NEXT, WM_SETFONT, 
  135.                             (WPARAM)hfont, TRUE);
  136.     }
  137. }
  138.  
  139.  
  140. /*************************************************************************
  141.  * GetViewerSR
  142.  *
  143.  * Returns the window handle of the scrolling region or NULL if the
  144.  * scrolling region is hidden or clipped out of view
  145.  *************************************************************************/
  146.  
  147. HWND GetViewerSR(VWR vwr)
  148. {
  149.     LONG lHwndSR = VwrGetInfo(vwr, GI_HWNDSRMAIN, 0, 0L); 
  150.     HWND hwndSR = LOWORD(lHwndSR);
  151.  
  152.     if(VwrGetInfo(vwr, GI_BOTADDR, hwndSR, 0L) == -1)
  153.         return NULL;
  154.     else
  155.         return hwndSR;
  156. }
  157.  
  158.  
  159.  
  160. /*************************************************************************
  161.  * GetViewerNSR
  162.  *
  163.  * Returns the window handle of the scrolling region or NULL if the
  164.  * non-scrolling region is hidden
  165.  *************************************************************************/
  166.  
  167. HWND GetViewerNSR(VWR vwr)
  168. {
  169.     LONG lHwndNSR = VwrGetInfo(vwr, GI_HWNDNSRMAIN, 0, 0L); 
  170.  
  171.     if(IsWindowVisible(LOWORD(lHwndNSR)))
  172.         return LOWORD(lHwndNSR);
  173.     else
  174.         return NULL;
  175. }
  176.  
  177.  
  178.  
  179. /***************************************************************************
  180.  * JumpPrevHighlight
  181.  *
  182.  * This function jumps to the first highlight above the visible
  183.  * portion of the topic. The function returns zero if successful or
  184.  * an error code if it can't jump to a previous highlight.
  185.  **************************************************************************/
  186.  
  187. int JumpPrevHighlight(
  188.     VWR vwr,                    // Handle to Viewer instance
  189.     HWND hwndViewer,            // Window handle of Viewer app
  190.     HANDLE hHighlight)          // Handle to highlight structure
  191. {
  192.     HWND hwndSR, hwndNSR;                   // Window handles
  193.     LONG lSRTopAddr;                        // Top address in SR
  194.     LONG lNSRBottomAddr;                    // Bottom address in NSR
  195.     LONG lSRNextMatch,  lSRNextMatchAddr;   // First match after top of SR
  196.     LONG lSRFirstMatch, lSRFirstMatchAddr;  // First match in topic SR
  197.     LONG lLen;                              // Match length
  198.     LONG lCurTopic;                         // Topic number of current topic
  199.  
  200.     LONG lPrev, lPrevAddr;                  // Previous match (the goal)
  201.  
  202.     // Get information about the layout of the scrolling region
  203.  
  204.     hwndSR = GetViewerSR(vwr);
  205.     if(hwndSR == NULL)
  206.         return KSERR_RESIZE_SL;
  207.  
  208.     lCurTopic = VwrGetInfo(vwr, GI_TOPICNO, hwndSR, 0L);    
  209.     lSRTopAddr = VwrGetInfo(vwr, GI_TOPADDR, hwndSR, 0L);
  210.  
  211.     // Determine the first match following the top of the scrolling region
  212.     // window. If the first match is number 0, there is no previous 
  213.     // highlight to jump to.
  214.  
  215.     lSRNextMatch = HighlightMatchFind(hHighlight, lCurTopic, lSRTopAddr, 
  216.                                        &lSRNextMatchAddr, &lLen);
  217.  
  218.     if(lSRNextMatch == 0)
  219.         return KSERR_NOPREVIOUS;
  220.  
  221.     // If the NSR is present, do some more checking to see if the first
  222.     // match following the top of the scrolling region window is actually
  223.     // the first match in the topic's scrolling region.
  224.  
  225.     hwndNSR = GetViewerNSR(vwr);
  226.     if(hwndNSR)
  227.     {
  228.         lNSRBottomAddr = VwrGetInfo(vwr, GI_BOTADDR, hwndNSR, 0L);        
  229.  
  230.         lSRFirstMatch = HighlightMatchFind(hHighlight, lCurTopic,
  231.                                lNSRBottomAddr, &lSRFirstMatchAddr,
  232.                                &lLen);
  233.  
  234.         if(lSRNextMatch == lSRFirstMatch)
  235.             return KSERR_NOPREVIOUS;
  236.     }
  237.  
  238.     // If there's no match following the top of the scrolling region 
  239.     // window, jump to the last highlight in the topic. Otherwise,
  240.     // jump to the highlight preceding the top of the scrolling region
  241.     // window.
  242.  
  243.     if(lSRNextMatch == -1)
  244.         lPrev = HighlightMatchCount(hHighlight, lCurTopic) - 1;
  245.     else
  246.         lPrev = lSRNextMatch - 1;
  247.  
  248.     HighlightMatchGet(hHighlight, lCurTopic, lPrev, &lPrevAddr, &lLen);
  249.  
  250.     // If there's a previous match, jump to it.
  251.  
  252.     return SubmitJumpAddr(vwr, lPrevAddr);
  253. }
  254.  
  255.  
  256.  
  257. /***************************************************************************
  258.  * JumpNextHighlight
  259.  *
  260.  * This function jumps to the next highlight following the visible
  261.  * portion of the topic. The function returns zero if successful or
  262.  * an error code if it can't jump to a next highlight.
  263.  *
  264.  * To calculate the address of the next highlight, we simply find the
  265.  * address of the last visible element in the topic and then request
  266.  * information for the highlight following that address.
  267.  *
  268.  **************************************************************************/
  269.  
  270. int JumpNextHighlight(
  271.     VWR vwr,                    // Handle to Viewer instance
  272.     HWND hwndViewer,            // Window handle of Viewer app
  273.     HANDLE hHighlight)          // Handle to highlight structure
  274. {
  275.     HWND hwndSR;                    // Scrolling region handle
  276.     LONG lAddrBottom, lAddrNext;    // Topic addresses
  277.     LONG lNext;                     // Ordinal of next highlight
  278.     LONG lHighlightLength;          // Highlight length
  279.     LONG lCurTopic;                 // Topic number of current topic
  280.  
  281.     // Get information about the layout of the scrolling region
  282.  
  283.     hwndSR = GetViewerSR(vwr);
  284.     if(hwndSR == NULL)
  285.         return KSERR_RESIZE_SL;
  286.  
  287.     lCurTopic = VwrGetInfo(vwr, GI_TOPICNO, hwndSR, 0L);    
  288.  
  289.     lAddrBottom = VwrGetInfo(vwr, GI_BOTADDR, hwndSR, 0L);
  290.  
  291.     // Determine the next match following the last topic element in the
  292.     // scrolling region window.
  293.  
  294.     lNext = HighlightMatchFind(hHighlight, lCurTopic, lAddrBottom, 
  295.                                 &lAddrNext, &lHighlightLength);
  296.  
  297.     if(lNext == -1)
  298.         return KSERR_NONEXT;
  299.  
  300.     // If there's a next match, jump to it.
  301.  
  302.     return SubmitJumpAddr(vwr, lAddrNext);
  303. }
  304.  
  305.  
  306. /**************************************************************************
  307.  *
  308.  * DrawResultsIcon
  309.  *
  310.  * This function draws the minimized Results window dialog box.
  311.  *
  312.  **************************************************************************/
  313.  
  314. void DrawResultsIcon(
  315.     HWND hwnd)              // Handle of results window
  316. {
  317.     HICON hicon = LoadIcon(ghModule, MAKEINTRESOURCE(ID_RESULTS_ICON));
  318.     PAINTSTRUCT ps;
  319.  
  320.     if(hicon == NULL)
  321.         return;
  322.  
  323.     BeginPaint(hwnd, &ps);
  324.  
  325.     DrawIcon(ps.hdc, 0, 0, hicon);
  326.  
  327.     EndPaint(hwnd, &ps);
  328. }
  329.  
  330.  
  331. /**************************************************************************
  332.  * ResultsDlgProc
  333.  *
  334.  * Dialog-box procedure for the Results window
  335.  *
  336.  **************************************************************************/
  337.  
  338. #define WM_USER_MAKEACTIVE WM_USER+1
  339.  
  340. BOOL CALLBACK ResultsDlgProc(
  341.     HWND   hwnd,                // Window handle
  342.     UINT   msg,                 // Message
  343.     WPARAM wParam,              // Message parameter
  344.     LPARAM lParam)              // Message parameter
  345. {
  346.     LPVWRINFO     lpVwrInfo;
  347.     int  iRet;
  348.     LONG lLBSel, lSelTopic;
  349.  
  350.     switch(msg)
  351.     {
  352.     case WM_INITDIALOG:
  353.  
  354.         // Retrieve the instance data for this task
  355.  
  356.         lpVwrInfo = GetTaskData(GetCurrentTask());
  357.         if(lpVwrInfo == NULL)
  358.         {
  359.             ShowMessage(GetParent(hwnd), KSERR_NOVWRINFO,
  360.                             MB_ICONEXCLAMATION);
  361.             DestroyWindow(hwnd);
  362.             return FALSE;
  363.         }
  364.  
  365.         // Tell Viewer to send us our messages
  366.  
  367.         if(lpVwrInfo->uiWMRegDlg)
  368.         {
  369.             SendMessage(lpVwrInfo->hwndViewer, lpVwrInfo->uiWMRegDlg, 
  370.                             (WPARAM)hwnd, 0L);
  371.         }
  372.         else
  373.         {
  374.             ShowMessage(GetParent(hwnd), KSERR_NOVWR,
  375.                             MB_ICONEXCLAMATION);
  376.             DestroyWindow(hwnd);
  377.             return FALSE;
  378.         }
  379.  
  380.         // Set topic counter to 0
  381.  
  382.         lpVwrInfo->lNextResult = 0;
  383.  
  384.         InitResultsControls(hwnd, lpVwrInfo->hfontDlg);
  385.  
  386.         // Set timer to start retrieval of topic titles. NOTE: to be safe,
  387.         // we should test the return value to see if the timer's available.
  388.         // If not, we could add all the topics to the results list as one
  389.         // operation.
  390.  
  391.         SetTimer(hwnd, 1, 50, NULL);
  392.  
  393.         // Apply the new highlight to the title
  394.  
  395.         SetHighlight(lpVwrInfo->vwr, lpVwrInfo->hHighlight);
  396.  
  397.         SetActiveWindow(hwnd);
  398.  
  399.         return TRUE;
  400.  
  401.     case WM_TIMER:
  402.         // Retrieve the instance data for this task
  403.  
  404.         lpVwrInfo = GetTaskData(GetCurrentTask());
  405.         if(lpVwrInfo == NULL)
  406.         {
  407.             ShowMessage(hwnd, KSERR_NOVWRINFO, MB_ICONEXCLAMATION);
  408.             KillTimer(hwnd, 1);
  409.             break;
  410.         }
  411.  
  412.         // If we're done, close the timer
  413.  
  414.         if(lpVwrInfo->lNextResult >= lpVwrInfo->lNumTopics)
  415.         {
  416.             KillTimer(hwnd, 1);
  417.  
  418.             return TRUE;
  419.         }
  420.  
  421.         // Add a topic title. If there are any problems, close the timer
  422.         // and the results window
  423.  
  424.         iRet = AddTopicTitle(GetDlgItem(hwnd, ID_RESULTS_LIST),
  425.                              lpVwrInfo->htitle, lpVwrInfo->htlResults, 
  426.                              lpVwrInfo->lNextResult);
  427.         if(iRet)
  428.         {
  429.             KillTimer(hwnd, 1);
  430.             ShowMessage(hwnd, KSERR_CANTCREATERESULTS, MB_ICONEXCLAMATION);
  431.             DestroyWindow(hwnd);
  432.  
  433.             return TRUE;
  434.         }
  435.  
  436.         if(lpVwrInfo->lNextResult == 0)
  437.             SendDlgItemMessage(hwnd, ID_RESULTS_LIST, LB_SETCURSEL, 0, 0L);
  438.  
  439.         lpVwrInfo->lNextResult++;
  440.  
  441.         return TRUE;
  442.  
  443.     case WM_ERASEBKGND:
  444.  
  445.         // Get the screen background for a minimized Results icon.
  446.  
  447.         if(IsIconic(hwnd))
  448.         {
  449.             DefWindowProc(hwnd, WM_ICONERASEBKGND, wParam, lParam);
  450.             return TRUE;
  451.         }
  452.         return FALSE;
  453.  
  454.     case WM_PAINT:
  455.  
  456.         // Paint the icon for the minimized Results dialog box.
  457.  
  458.         if(IsIconic(hwnd))
  459.         {
  460.             DrawResultsIcon(hwnd);
  461.         }
  462.         return FALSE;
  463.  
  464.     case WM_USER_MAKEACTIVE:
  465.         SetActiveWindow(hwnd);
  466.         return TRUE;
  467.  
  468.     case WM_COMMAND:
  469.         switch(wParam)
  470.         {
  471.         case ID_RESULTS_LIST:
  472.             if(HIWORD(lParam) != LBN_DBLCLK)
  473.                 return TRUE;
  474.  
  475.             lpVwrInfo = GetTaskData(GetCurrentTask());
  476.             if(lpVwrInfo == NULL)
  477.             {
  478.                 ShowMessage(hwnd, KSERR_NOVWRINFO, MB_ICONEXCLAMATION);
  479.                 return TRUE;
  480.             }
  481.  
  482.             // Get selected topic from list box
  483.  
  484.             lLBSel = SendMessage(LOWORD(lParam), LB_GETCURSEL, 0, 0L);
  485.  
  486.             // Get topic number from topic list
  487.  
  488.             lSelTopic = TopicListLookup(lpVwrInfo->htlResults, lLBSel);
  489.             if(lSelTopic == -1)
  490.             {
  491.                 ShowMessage(hwnd, KSERR_DISPLAYFAILED, MB_ICONEXCLAMATION);
  492.                 return TRUE;
  493.             }
  494.  
  495.             iRet = DisplayTopic(lpVwrInfo->htitle, lpVwrInfo->vwr,
  496.                                 lSelTopic);
  497.             if(iRet)
  498.             {
  499.                 ShowMessage(hwnd, KSERR_DISPLAYFAILED, MB_ICONEXCLAMATION);
  500.             }
  501.                 
  502.             // Get the focus back from Viewer
  503.  
  504.             PostMessage(hwnd, WM_USER_MAKEACTIVE, 0, 0L);
  505.  
  506.             return TRUE;
  507.  
  508.         case ID_RESULTS_NEXT:
  509.             // Jump to next highlight in selected topic
  510.  
  511.             lpVwrInfo = GetTaskData(GetCurrentTask());
  512.             if(lpVwrInfo == NULL)
  513.             {
  514.                 ShowMessage(hwnd, KSERR_NOVWRINFO, MB_ICONEXCLAMATION);
  515.                 break;
  516.             }
  517.  
  518.             iRet = JumpNextHighlight(lpVwrInfo->vwr, lpVwrInfo->hwndViewer,
  519.                         lpVwrInfo->hHighlight);
  520.             if(iRet)
  521.                 ShowMessage(hwnd, iRet, MB_ICONEXCLAMATION);
  522.  
  523.             // Get the focus back from Viewer
  524.  
  525.             PostMessage(hwnd, WM_USER_MAKEACTIVE, 0, 0L);
  526.  
  527.             return TRUE;
  528.  
  529.         case ID_RESULTS_PREVIOUS:
  530.             // Jump to preceding highlight in selected topic
  531.  
  532.             lpVwrInfo = GetTaskData(GetCurrentTask());
  533.             if(lpVwrInfo == NULL)
  534.             {
  535.                 ShowMessage(hwnd, KSERR_NOVWRINFO, MB_ICONEXCLAMATION);
  536.                 break;
  537.             }
  538.  
  539.             iRet = JumpPrevHighlight(lpVwrInfo->vwr, lpVwrInfo->hwndViewer,
  540.                         lpVwrInfo->hHighlight);
  541.             if(iRet)
  542.                 ShowMessage(hwnd, iRet, MB_ICONEXCLAMATION);
  543.  
  544.             // Get the focus back from Viewer
  545.  
  546.             PostMessage(hwnd, WM_USER_MAKEACTIVE, 0, 0L);
  547.  
  548.             return TRUE;
  549.         }
  550.         break;
  551.  
  552.     case WM_CLOSE:
  553.         // Retrieve the instance data for this task
  554.  
  555.         lpVwrInfo = GetTaskData(GetCurrentTask());
  556.         if(lpVwrInfo == NULL)
  557.         {
  558.             ShowMessage(hwnd, KSERR_NOVWRINFO, MB_ICONEXCLAMATION);
  559.             break;
  560.         }
  561.  
  562.         // Cancel the highlight. We do this here rather than in WM_DESTROY.
  563.         // The DLL destroys the Results window when a new title is being
  564.         // loaded--in that case, we don't need to reset the highlight.
  565.  
  566.         SetHighlight(lpVwrInfo->vwr, 0);
  567.  
  568.         DestroyWindow(hwnd);
  569.  
  570.         break;
  571.  
  572.     case WM_DESTROY:
  573.         // Retrieve the instance data for this task
  574.  
  575.         lpVwrInfo = GetTaskData(GetCurrentTask());
  576.         if(lpVwrInfo == NULL)
  577.         {
  578.             ShowMessage(hwnd, KSERR_NOVWRINFO, MB_ICONEXCLAMATION);
  579.             break;
  580.         }
  581.  
  582.         // Clean up the topic list and highlight structures
  583.  
  584.         lpVwrInfo->hwndResults = NULL;
  585.  
  586.         if(lpVwrInfo->htlResults)
  587.         {
  588.             TopicListDestroy(lpVwrInfo->htlResults);
  589.             lpVwrInfo->htlResults = NULL;
  590.         }
  591.  
  592.         if(lpVwrInfo->hHighlight)
  593.         {
  594.             HighlightDestroy(lpVwrInfo->hHighlight);
  595.             lpVwrInfo->hHighlight = NULL;
  596.         }
  597.  
  598.         // Tell Viewer to stop sending us messages
  599.  
  600.         if(lpVwrInfo->uiWMRegDlg)
  601.         {
  602.             SendMessage(lpVwrInfo->hwndViewer, lpVwrInfo->uiWMRegDlg, 
  603.                             NULL, 0L);
  604.         }    
  605.         break;
  606.  
  607.     }
  608.     return FALSE;
  609. }
  610.  
  611.  
  612.  
  613.  
  614.